/*******************************************************************************
 * Copyright 2007-2014 FZI, http://www.fzi.de
 *                 Forschungszentrum Informatik - Information Process Engineering (IPE)
 *  
 *                 See the NOTICE file distributed with this work for additional
 *                 information regarding copyright ownership
 *                
 *                 Licensed under the Apache License, Version 2.0 (the "License");
 *                 you may not use this file except in compliance with the License.
 *                 You may obtain a copy of the License at
 *                
 *                   http://www.apache.org/licenses/LICENSE-2.0
 *                
 *                 Unless required by applicable law or agreed to in writing, software
 *                 distributed under the License is distributed on an "AS IS" BASIS,
 *                 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *                 See the License for the specific language governing permissions and
 *                 limitations under the License.
 * @author tzentek - <a href="mailto:zentek@fzi.de">Tom Zentek</a>
 * @author cyumusak - <a href="mailto:canyumusak@gmail.com">Can Yumusak</a>
 ******************************************************************************/
package de.fzi.fhemapi.view.vaadin.ui.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import de.fzi.fhemapi.model.actuatorparameters.ActuatorParameters;
import de.fzi.fhemapi.server.core.ManufacturerManager;

/**
 * This class builds the bridge between an ActuatorParameter and it's parameters.
 * @author Can Yumusak
 *
 */
public class ParameterExtractor {

	/**
	 * Returns the parameternames of the constructor of a class.
	 * @param className the name of the class.
	 * @return a StringArray with the parameternames.
	 */
	public static String[] getParameters(String className){
		Class<? extends ActuatorParameters> deviceClass = getClassFromName(className);
		if(deviceClass  == null) return null;
		
		Method method;
		String[] parameterNames = null;
		try {
			method = deviceClass.getMethod("getParameterNames");
			parameterNames = (String[]) method.invoke(null);
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
		if(parameterNames == null) return new String[]{};
		
		return parameterNames;
	}
	
	/**
	 * Returns an instantiated ActuatorParameters on base of a classname and it's parameters.
	 * @param className the class name to instantiate
	 * @param params the parameters to instantiate the ActuatorParameters
	 * @return
	 */
	public static ActuatorParameters getJavaParameters(String className, String[] params){
		Class<? extends ActuatorParameters> deviceClass = getClassFromName(className);
		Constructor<?>[] constructors = deviceClass.getConstructors();
		Constructor<?> constr = null;
		for(Constructor<?> constructor : constructors){
			if(constructor.getParameterTypes().length == params.length){
				constr = constructor;
				break;
			}
		}
		Object[] parameterObject = new Object[params.length];
		for(int i = 0; i < params.length; i++){
			parameterObject[i] = params[i];
		}
		
		ActuatorParameters returnParams = null;
		try {
			returnParams = (ActuatorParameters) constr.newInstance(parameterObject);
		} catch (InstantiationException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnParams;
	}
	
	private static Class<? extends ActuatorParameters> getClassFromName(String name){
		List<Class<? extends ActuatorParameters>> classes = ManufacturerManager.getClasses();
		Class<? extends ActuatorParameters> deviceClass = null;
		for(Class<? extends ActuatorParameters> clazz : classes){
			if(clazz.getSimpleName().equals(name))
				deviceClass = clazz;
		}
		
		return deviceClass;
	}
}
